package com.example.treemap.client;

import com.google.gwt.canvas.client.Canvas;
import com.google.gwt.canvas.dom.client.Context2d;
import com.google.gwt.canvas.dom.client.CssColor;
import com.google.gwt.user.client.Random;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.RootPanel;

public class DrawSplitTreemap_Canvas {
	
	// Variables required
	private double X = 0.0 ,Y = 0.0 ,Width,Height;
	
	// Creating the canvas
	private Canvas canvas = Canvas.createIfSupported();
	
	public void DrawSplitTreemapCanvas(Node L[],int n,int x,int y,int width,int height) {
		
		if( canvas == null )
			Window.alert("Canvas is not supported by browser");
		
		else{
				// Created the canvas of the required size
			 	canvas.setCoordinateSpaceWidth(width);
			 	canvas.setCoordinateSpaceHeight(height);
			 	canvas.setStyleName("Canvas");	 	
			 	RootPanel.get().add(canvas,x,y);
			 	
			 	Width = width;
			 	Height = height;
			 	
			 	Sort_Data(L,n);
			 	Algorithm(L, n, X, Y, Width, Height);
			 	
		}	
		
	}
	
	private void Sort_Data(Node array[],int size) {
        
        for(int i = 0 ; i < size ; i++ ) {
                
                for(int j = i + 1 ; j < size ; j++ ) {
                        
                        if( array[i].ReturnNumber() > array[j].ReturnNumber() ) {
                                
                                Node temp = new Node();
                                
                                temp = array[i];
                                array[i] = array[j];
                                array[j] = temp;
                        
                        }
                        
                }
        }
        
	}
	
	private void Algorithm(Node L[],int n,double X, double Y, double Width, double Height ){
        
        if( n > 1 ){
                
                // Variables
                        // required variables for weight
                                int wl,wl1;
                        
                        // Array variables and their required part
                                Node[] L1 = new Node[1000];
                                Node[] L2 = new Node[1000];
                                
                                int n1 = 0 ,n2 = 0;
                                
                        // Variables for splitting the array
                                double halfsize,w1 = 0,temp = 0;
                                
                        // Variables for indices
                                int i,j;
                                
                        // new values for x,y width and height that would be used by L2
                                double newX,newY,newWidth,newHeight,Width1,Height1;
                        
                // Step 1 - Get the weight of the current array
                        wl = Get_Weight(L,n);
                    
                // Step 2 - Divide the array into two array as per the algorithm
                        halfsize = wl / 2.0;
                        
                        for( i = 0 ; i < n ; i++ ){
                                
                                temp = w1 + L[i].ReturnNumber();
                                
                                if( ( Math.abs( halfsize - temp ) ) > ( Math.abs( halfsize - w1 ) ) )
                                        break; 
                                
                                L1[i] = L[i];
                                w1 = temp;
                                
                        }
                        
                        n1 = i;
                        
                        for( j = i ; j < n ; j++,n2++ )
                                L2[n2] = L[j];
                        
                // Step 3 - Get the weight of L1
                        wl1 = Get_Weight(L1,n1);
                        
                // Step 4 - Get the area for new rectangle
                        double area1 = ( wl1 * Width * Height ) / wl;
                        
                // Now as per the length of width and height divide get the values for new rectangles
                        if( Width > Height ){
                                
                                // Changes occurring in L1 
                                Width1 = area1 / Height;
                                Height1 = Height;
                                
                                // getting the new values for L2 as L1 X, Y and width or height would remain same 
                                newX = X + Width1;
                                newY = Y;
                                newWidth = Width - Width1;
                                newHeight = Height;
                        }
                        else {
                                
                                // Changes occurring in L1
                                        Width1 = Width;
                                        Height1 = area1 / Width;
                                
                                // Getting new values for L2
                                        newX = X;
                                        newY = Y + Height1;
                                        newWidth = Width;
                                        newHeight = Height - Height1;
                                
                        }
                        
                // Call the methods again for full implementation
                        Algorithm(L1,n1,X,Y,Width1,Height1);
                        Algorithm(L2,n2,newX,newY,newWidth,newHeight);
        }
        else if( n == 1 ){
                       
        		// Just draw the rectangle
                        Draw_Rect(L[0].ReturnInfo(),L[0].ReturnNumber(),X, Y, Width, Height);
                        
                        return;
        }
        
	}

	private int Get_Weight(Node arr[],int size){
        
        int sum = 0;
        
        for( int i = 0 ; i < size ; i++ ) { 
            sum = sum + arr[i].ReturnNumber();
        }
        
        return sum;
	}
	
	private void Draw_Rect(String info,int num,double x,double y,double width,double height) {
		
		Context2d context;
		int x1,y1,width1,height1;
		int red,blue,green;
		double trans;
		String complete;
		
		context = canvas.getContext2d();
	
		// Convert double to integer
		x1 = (int) x;
		y1 = (int) y;
		width1 = (int) width;
		height1 = (int) height;
		
		// generate random colors
		red = Random.nextInt(255);
		blue = Random.nextInt(255);
		green = Random.nextInt(255);
		trans = Random.nextDouble();
		
		CssColor color = CssColor.make("rgba(" + red + ", " + green + "," + blue + ", " + trans + ")");
		context.setFillStyle(color);
        context.fillRect( x1, y1, width1, height1);
        context.strokeRect( x1, y1, width1, height1);
        context.fill();
        
        complete = info + " " + Integer.toString(num);
        context.setFillStyle("black");
        context.setFont("15px Arial");
        context.fillText(complete, x1, y1 + (height1 / 2));
        
	}
	

}
